import json
import os
import sys
from datetime import datetime

# 添加父目录到路径以支持导入
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
models_dir = os.path.join(parent_dir, "models")
if models_dir not in sys.path:
    sys.path.insert(0, models_dir)

try:
    from order import Order
except ImportError:
    # 如果无法导入 Order，创建一个临时的 Order 类
    class Order:
        STATUS_PENDING = "Pending"
        STATUS_PROCESSING = "Processing"
        STATUS_DELIVERED = "Delivered"
        
        def __init__(self):
            pass


class Shipment:
    """
    物流信息类，用于跟踪订单中每个商品的物流状态
    """
    # 物流状态常量
    STATUS_PENDING = "Pending"
    STATUS_PROCESSING = "Processing"
    STATUS_SHIPPED = "Shipped"
    STATUS_IN_TRANSIT = "In Transit"
    STATUS_OUT_FOR_DELIVERY = "Out for Delivery"
    STATUS_DELIVERED = "Delivered"
    STATUS_EXCEPTION = "Exception"
    STATUS_RETURNED = "Returned"
    
    def __init__(self, shipment_id, order_id, product_id, product_name, quantity, price):
        self._shipment_id = shipment_id
        self._order_id = order_id
        self._product_id = product_id
        self._product_name = product_name
        self._quantity = quantity
        self._price = price
        self._status = Shipment.STATUS_PENDING
        self._tracking_number = None
        self._carrier = None
        self._estimated_delivery = None
        self._actual_delivery = None
        self._current_location = None
        self._created_at = datetime.now()
        self._updated_at = datetime.now()
        self._status_history = [
            {
                "status": self._status,
                "timestamp": self._created_at,
                "location": None,
                "description": "订单创建，等待处理"
            }
        ]
    
    def update_status(self, status, location=None, description=None):
        """
        更新物流状态
        """
        valid_statuses = [
            Shipment.STATUS_PENDING,
            Shipment.STATUS_PROCESSING,
            Shipment.STATUS_SHIPPED,
            Shipment.STATUS_IN_TRANSIT,
            Shipment.STATUS_OUT_FOR_DELIVERY,
            Shipment.STATUS_DELIVERED,
            Shipment.STATUS_EXCEPTION,
            Shipment.STATUS_RETURNED
        ]
        
        if status in valid_statuses:
            self._status = status
            self._updated_at = datetime.now()
            self._current_location = location
            
            # 记录状态历史
            status_entry = {
                "status": status,
                "timestamp": self._updated_at,
                "location": location,
                "description": description or f"状态更新为: {status}"
            }
            self._status_history.append(status_entry)
            
            # 如果是已送达状态，记录实际送达时间
            if status == Shipment.STATUS_DELIVERED:
                self._actual_delivery = self._updated_at
            
            return True
        return False
    
    def set_tracking_info(self, tracking_number, carrier, estimated_delivery=None):
        """
        设置物流单号和承运商信息
        """
        self._tracking_number = tracking_number
        self._carrier = carrier
        self._estimated_delivery = estimated_delivery
        
        # 如果设置了物流信息，自动更新状态为已发货
        if self._status == Shipment.STATUS_PROCESSING:
            self.update_status(
                Shipment.STATUS_SHIPPED,
                description=f"商品已发货，承运商: {carrier}，物流单号: {tracking_number}"
            )
    
    def get_latest_status(self):
        """
        获取最新的物流状态
        """
        return self._status_history[-1]
    
    def get_delivery_delay(self):
        """
        获取物流延迟时间（如果有）
        """
        if self._actual_delivery and self._estimated_delivery:
            delay = self._actual_delivery - self._estimated_delivery
            return delay.total_seconds() / 86400  # 转换为天数
        return None
    
    def to_dict(self):
        """
        转换为字典格式
        """
        return {
            "shipment_id": self._shipment_id,
            "order_id": self._order_id,
            "product_id": self._product_id,
            "product_name": self._product_name,
            "quantity": self._quantity,
            "price": self._price,
            "status": self._status,
            "tracking_number": self._tracking_number,
            "carrier": self._carrier,
            "estimated_delivery": self._estimated_delivery.isoformat() if self._estimated_delivery else None,
            "actual_delivery": self._actual_delivery.isoformat() if self._actual_delivery else None,
            "current_location": self._current_location,
            "created_at": self._created_at.isoformat(),
            "updated_at": self._updated_at.isoformat(),
            "status_history": [
                {
                    "status": entry["status"],
                    "timestamp": entry["timestamp"].isoformat(),
                    "location": entry["location"],
                    "description": entry["description"]
                }
                for entry in self._status_history
            ]
        }
    
    @classmethod
    def from_dict(cls, data):
        """
        从字典创建物流对象
        """
        shipment = cls(
            shipment_id=data["shipment_id"],
            order_id=data["order_id"],
            product_id=data["product_id"],
            product_name=data["product_name"],
            quantity=data["quantity"],
            price=data["price"]
        )
        
        shipment._status = data["status"]
        shipment._tracking_number = data["tracking_number"]
        shipment._carrier = data["carrier"]
        shipment._estimated_delivery = datetime.fromisoformat(data["estimated_delivery"]) if data["estimated_delivery"] else None
        shipment._actual_delivery = datetime.fromisoformat(data["actual_delivery"]) if data["actual_delivery"] else None
        shipment._current_location = data["current_location"]
        shipment._created_at = datetime.fromisoformat(data["created_at"])
        shipment._updated_at = datetime.fromisoformat(data["updated_at"])
        
        # 恢复状态历史
        shipment._status_history = [
            {
                "status": entry["status"],
                "timestamp": datetime.fromisoformat(entry["timestamp"]),
                "location": entry["location"],
                "description": entry["description"]
            }
            for entry in data["status_history"]
        ]
        
        return shipment
    
    # Getter方法
    @property
    def shipment_id(self):
        return self._shipment_id
    
    @property
    def order_id(self):
        return self._order_id
    
    @property
    def product_id(self):
        return self._product_id
    
    @property
    def product_name(self):
        return self._product_name
    
    @property
    def quantity(self):
        return self._quantity
    
    @property
    def price(self):
        return self._price
    
    @property
    def status(self):
        return self._status
    
    @property
    def tracking_number(self):
        return self._tracking_number
    
    @property
    def carrier(self):
        return self._carrier
    
    @property
    def current_location(self):
        return self._current_location
    
    @property
    def status_history(self):
        return self._status_history


class ShipmentManager:
    """
    物流管理器类，负责管理所有物流信息
    """
    def __init__(self, data_file="shipments.json", order_manager=None, product_manager=None):
        self._shipments = {}
        self._data_file = data_file
        self._order_manager = order_manager
        self._product_manager = product_manager
        self._load_shipments()
    
    def _load_shipments(self):
        """
        从文件加载物流数据
        """
        try:
            with open(self._data_file, 'r', encoding='utf-8') as f:
                shipments_data = json.load(f)
                for shipment_data in shipments_data:
                    shipment = Shipment.from_dict(shipment_data)
                    self._shipments[shipment.shipment_id] = shipment
        except FileNotFoundError:
            pass
        except json.JSONDecodeError:
            pass
        except Exception as e:
            print(f"加载物流数据时出错: {e}")
    
    def save_shipments(self):
        """
        保存物流数据到文件
        """
        shipments_data = [shipment.to_dict() for shipment in self._shipments.values()]
        
        with open(self._data_file, 'w', encoding='utf-8') as f:
            json.dump(shipments_data, f, ensure_ascii=False, indent=2)
    
    def create_shipments_from_order(self, order):
        """
        从订单创建物流信息
        """
        shipments = []
        
        for item in order.items:
            # 生成物流ID
            shipment_id = f"s{order.order_id[1:]}_{item.product.product_id[:6]}"
            
            # 创建物流记录
            shipment = Shipment(
                shipment_id=shipment_id,
                order_id=order.order_id,
                product_id=item.product.product_id,
                product_name=item.product.name,
                quantity=item.quantity,
                price=item.price
            )
            
            # 更新物流状态为处理中
            shipment.update_status(
                Shipment.STATUS_PROCESSING,
                description="订单已支付，正在处理中"
            )
            
            self._shipments[shipment.shipment_id] = shipment
            shipments.append(shipment)
        
        # 保存物流数据
        self.save_shipments()
        
        # 如果有订单管理器，更新订单状态
        if self._order_manager:
            self._order_manager.update_order_status(order.order_id, Order.STATUS_PROCESSING)
        
        return shipments
    
    def get_shipment_by_id(self, shipment_id):
        """
        通过ID获取物流信息
        """
        return self._shipments.get(shipment_id)
    
    def get_shipments_by_order_id(self, order_id):
        """
        获取订单的所有物流信息
        """
        return [shipment for shipment in self._shipments.values() 
                if shipment.order_id == order_id]
    
    def get_shipments_by_product_id(self, product_id):
        """
        获取商品的所有物流信息
        """
        return [shipment for shipment in self._shipments.values() 
                if shipment.product_id == product_id]
    
    def update_shipment_status(self, shipment_id, status, location=None, description=None):
        """
        更新物流状态
        """
        shipment = self.get_shipment_by_id(shipment_id)
        if shipment and shipment.update_status(status, location, description):
            self.save_shipments()
            
            # 如果物流状态更新为已送达，更新相关订单状态
            if status == Shipment.STATUS_DELIVERED:
                order_id = shipment.order_id
                # 检查订单中所有物流是否都已送达
                all_delivered = True
                for s in self.get_shipments_by_order_id(order_id):
                    if s.status != Shipment.STATUS_DELIVERED:
                        all_delivered = False
                        break
                
                # 如果所有商品都已送达，更新订单状态
                if all_delivered and self._order_manager:
                    self._order_manager.update_order_status(order_id, Order.STATUS_DELIVERED)
            
            return True
        return False
    
    def set_shipment_tracking_info(self, shipment_id, tracking_number, carrier, estimated_delivery=None):
        """
        设置物流追踪信息
        """
        shipment = self.get_shipment_by_id(shipment_id)
        if shipment:
            shipment.set_tracking_info(tracking_number, carrier, estimated_delivery)
            self.save_shipments()
            return True
        return False
    
    def get_all_shipments(self):
        """
        获取所有物流信息
        """
        return list(self._shipments.values())
    
    def get_shipments_by_status(self, status):
        """
        根据状态获取物流信息
        """
        return [shipment for shipment in self._shipments.values() 
                if shipment.status == status]
    
    def get_shipments_by_carrier(self, carrier):
        """
        根据承运商获取物流信息
        """
        return [shipment for shipment in self._shipments.values() 
                if shipment.carrier == carrier]
    
    def get_delayed_shipments(self):
        """
        获取延迟的物流信息
        """
        delayed = []
        now = datetime.now()
        
        for shipment in self._shipments.values():
            # 检查未送达且超出预计送达时间的物流
            if (shipment.estimated_delivery and 
                shipment.status != Shipment.STATUS_DELIVERED and 
                now > shipment.estimated_delivery):
                delayed.append(shipment)
        
        return delayed
    
    def get_shipment_statistics(self):
        """
        获取物流统计信息
        """
        stats = {
            "total_shipments": len(self._shipments),
            "status_counts": {},
            "carrier_counts": {},
            "average_delivery_time": 0,
            "delayed_count": 0
        }
        
        delivery_times = []
        delayed_count = 0
        now = datetime.now()
        
        for shipment in self._shipments.values():
            # 统计各状态数量
            if shipment.status not in stats["status_counts"]:
                stats["status_counts"][shipment.status] = 0
            stats["status_counts"][shipment.status] += 1
            
            # 统计各承运商数量
            if shipment.carrier:
                if shipment.carrier not in stats["carrier_counts"]:
                    stats["carrier_counts"][shipment.carrier] = 0
                stats["carrier_counts"][shipment.carrier] += 1
            
            # 计算实际配送时间
            if shipment.status == Shipment.STATUS_DELIVERED and shipment.actual_delivery:
                delivery_time = (shipment.actual_delivery - shipment._created_at).total_seconds() / 86400  # 转换为天数
                delivery_times.append(delivery_time)
            
            # 统计延迟数量
            if (shipment.estimated_delivery and 
                shipment.status != Shipment.STATUS_DELIVERED and 
                now > shipment.estimated_delivery):
                delayed_count += 1
        
        # 计算平均配送时间
        if delivery_times:
            stats["average_delivery_time"] = sum(delivery_times) / len(delivery_times)
        
        stats["delayed_count"] = delayed_count
        
        return stats